﻿#include "CatHttpTools.h"
#include <QDir>
#include <QUrl>
#include <QNetworkAccessManager>

CatHttpTools::CatHttpTools(QObject *parent)
    : QThread(parent)
{
    m_yState = INOPERATION;
}

CatHttpTools::~CatHttpTools()
{
    m_yState = INOPERATION;
    if(this->isRunning())
    {
        m_yCondition.wakeAll();
    }
}

void CatHttpTools::DownLoad(QUrl url, QString downloadir, bool ssl)
{
    if(m_yState == INOPERATION)
    {
        m_yState = DOWNLOAD;
        m_sDownLoadPath = downloadir;
        m_bSSL = ssl;
        m_pUrl = url;
        this->start();
    }
}

int CatHttpTools::DownLoad()
{
    QDir dir;
    if(!dir.exists(m_sDownLoadPath))
    {
        if(!dir.mkpath(m_sDownLoadPath))
        {
            return -1;
        }
    }

    QFileInfo info(m_pUrl.path());
    QString fileName(info.fileName());
    QString file = m_sDownLoadPath + fileName;
    DownLoadFile = new QFile(file);
    Manager = new QNetworkAccessManager();
    if(!DownLoadFile->open(QIODevice::WriteOnly))
    {
        DownLoadFile->deleteLater();
        DownLoadFile = nullptr;
        return -1;
    }

    if(!m_bSSL)
    {
        Reply = Manager->get(QNetworkRequest(m_pUrl));
    } else {
        QNetworkRequest request;
        QSslConfiguration config;
        QSslConfiguration conf = request.sslConfiguration();
        conf.setPeerVerifyMode(QSslSocket::VerifyNone);
        conf.setProtocol(QSsl::TlsV1SslV3);
        request.setSslConfiguration(conf);
        request.setUrl(m_pUrl);
        Reply = Manager->get(request);
    }

    connect(Reply, SIGNAL(readyRead()), this, SLOT(On_HttpReadyRead()));
    connect(Reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(On_UpdateDataReadProgress(qint64, qint64)));
    connect(Reply, SIGNAL(finished()), this, SLOT(On_HttpFinished()));
    connect(Reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(On_HttpError(QNetworkReply::NetworkError)));


    return 0;
}

void CatHttpTools::DeleteDownLoad()
{
    if(Reply != nullptr)
    {
        Reply->deleteLater();
        Reply = nullptr;
    }

    if(Manager != nullptr)
    {
        Manager->deleteLater();
        Manager = nullptr;
    }

    if(DownLoadFile != nullptr)
    {
        DownLoadFile->deleteLater();
        DownLoadFile = nullptr;
    }
}

void CatHttpTools::run()
{
    switch (m_yState) {
        case DOWNLOAD: {
            if(DownLoad() != 0)
            {
                m_yState = INOPERATION;
                return;
            }
            break;
        }
        default:{
            break;
        }
    }

    m_yMutex.lock();
    m_yCondition.wait(&m_yMutex);
    m_yMutex.unlock();

    switch (m_yState) {
        case DOWNLOAD: {
            DeleteDownLoad();
            break;
        }
        default:{
            break;
        }
    }

    m_yState = INOPERATION;
}

void CatHttpTools::On_HttpFinished()
{
    DownLoadFile->flush();
    DownLoadFile->close();
    Reply->deleteLater();
    Reply = nullptr;
    DownLoadFile->deleteLater();
    DownLoadFile = nullptr;

    QFileInfo info(m_pUrl.path());
    QString fileName(info.fileName());
    QString file = m_sDownLoadPath + fileName;

    m_yCondition.wakeAll();
    emit DownLoadFinished(file);
}

void CatHttpTools::On_HttpReadyRead()
{
    switch (m_yState) {
        case DOWNLOAD: {
            DownLoadFile->write(Reply->readAll());
            break;
        }
        default:{
            break;
        }
    }
}

void CatHttpTools::On_HttpError(QNetworkReply::NetworkError error)
{
    qDebug() << "Error: " << error;
    switch (m_yState) {
        case DOWNLOAD: {
            DownLoadFile->flush();
            DownLoadFile->close();
            Reply->deleteLater();
            Reply = nullptr;
            DownLoadFile->deleteLater();
            DownLoadFile = nullptr;
            m_yCondition.wakeAll();
            emit DownLoadError();
            break;
        }
        default: {
            break;
        }
    }
}

void CatHttpTools::On_UpdateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
    qDebug() << "Update: " << bytesRead << " : " << totalBytes;
    emit DownLoadProgress(bytesRead, totalBytes);
}
